#pragma once


#include "DataStructure/Input/Node/NodeData.h"
#include "DataStructure/Input/Solver/DOFDirections.h"
#include "DataStructure/Input/Solver/Subcase.h"
#include "DataStructure/Input/Property/PSOLIDData.h"
#include "DBManager/Database/DatabaseFactory.h"
#include "DBManager/DBServiceFactory.h"
#include "DBManager/IService/Input/Subcase/ISubcaseService.h"
#include "DBManager/IService/Input/Node/INodeService.h"
#include "DBManager/IService/Input/Element/IElementService.h"
#include "DBManager/IService/Input/Coordinate/ICORD1CService.h"

#include "DBManager/IService/Input/Constraint/ISPCService.h"
#include "DBManager/IService/Input/Material/IIsotropicMaterialService.h"
#include "DBManager/IService/Input/Property/IPSOLIDService.h"

using SG::DataStructure::FEM::DOFDirections;
using SG::DataStructure::FEM::DofSet2Int;
using SG::DataStructure::FEM::PSOLIDData;
using namespace SG::DBManager;
extern std::shared_ptr<DBServiceFactory> DB_SERVICEFACTORY;

/// Penta模型数据
class Penta6OneEleModel
{
  public:
    Penta6OneEleModel ()
    {
        DB_SERVICEFACTORY->ClearDatabase ();
        Input (DB_SERVICEFACTORY);
    }

    /// @brief 写入模型数据
    void               Input (const DBServiceFactorySP dbServiceFactory);
    DBServiceFactorySP GetModel ()
    {
        return DB_SERVICEFACTORY;
    }

};

void Penta6OneEleModel::Input (const DBServiceFactorySP dbServiceFactory)
{
    // 节点写入
    {
        SG::DataStructure::FEM::NodeData node;
        node.m_dispCoord = 100;
        node.m_id   = 1;
        node.m_x[0] = 0.0;
        node.m_x[1] = 10.0;
        node.m_x[2] = 10.0;
        dbServiceFactory->get<INodeService> ()->Add (node);

        node.m_dispCoord = 0;
        node.m_id   = 2;
        node.m_x[0] = 5.0;
        node.m_x[1] = 5.0;
        node.m_x[2] = 10.0;
        dbServiceFactory->get<INodeService> ()->Add (node);
        node.m_id   = 3;
        node.m_x[0] = 10.0;
        node.m_x[1] = 10.0;
        node.m_x[2] = 10.0;
        dbServiceFactory->get<INodeService> ()->Add (node);
        node.m_id   = 4;
        node.m_x[0] = 0.0;
        node.m_x[1] = 10.0;
        node.m_x[2] = 20.0;
        dbServiceFactory->get<INodeService> ()->Add (node);
        node.m_id   = 5;
        node.m_x[0] = 5.0;
        node.m_x[1] = 5.0;
        node.m_x[2] = 20.0;
        dbServiceFactory->get<INodeService> ()->Add (node);
        node.m_id   = 6;
        node.m_x[0] = 10.0;
        node.m_x[1] = 10.0;
        node.m_x[2] = 20.0;
        dbServiceFactory->get<INodeService> ()->Add (node);
        node.m_id   = 7;
        node.m_x[0] = 5.0;
        node.m_x[1] = 9.0;
        node.m_x[2] = 2.0;
        dbServiceFactory->get<INodeService> ()->Add (node);
        node.m_id   = 8;
        node.m_x[0] = 0.0;
        node.m_x[1] = 1.0;
        node.m_x[2] = 8.0;
        dbServiceFactory->get<INodeService> ()->Add (node);
        node.m_id   = 9;
        node.m_x[0] = 18.0;
        node.m_x[1] = 1.0;
        node.m_x[2] = 16.0;
        dbServiceFactory->get<INodeService> ()->Add (node);
    }

    // 柱坐标系
    {
        SG::DataStructure::FEM::CORD1CData cord1C;
        cord1C.m_id = 100;
        cord1C.m_g1 = 8;
        cord1C.m_g2 = 9;
        cord1C.m_g3 = 7;
        dbServiceFactory->get<ICORD1CService> ()->Add (cord1C);
    }

    // 单元写入
    {
        SG::DataStructure::FEM::CPENTA6Data pentaEle;
        pentaEle.m_id   = 1;
        pentaEle.m_pId  = 1;
        pentaEle.m_g[0] = 1;
        pentaEle.m_g[1] = 2;
        pentaEle.m_g[2] = 3;
        pentaEle.m_g[3] = 4;
        pentaEle.m_g[4] = 5;
        pentaEle.m_g[5] = 6;
        dbServiceFactory->get<IElementService> ()->Add (pentaEle);
    }

    // 节点固定约束 SPC1
    {
        SG::DataStructure::FEM::SPCData spc;
        spc.m_sId = 1;
        spc.m_g   = 1;
        spc.m_c   = DofSet2Int ({ DOFDirections::DOF_Ux, DOFDirections::DOF_Uy, DOFDirections::DOF_Uz });
        dbServiceFactory->get<ISPCService> ()->Add (spc);

        spc.m_g   = 2;
        spc.m_c   = DofSet2Int ({ DOFDirections::DOF_Ux, DOFDirections::DOF_Uy, DOFDirections::DOF_Uz });
        dbServiceFactory->get<ISPCService> ()->Add (spc);
    }

    // 材料写入
    {
        SG::DataStructure::FEM::IsotropicMaterial material;
        material.m_id = 1;
        material.m_E  = 70000.0;
        material.m_nu = 0.33;
        material.m_rho = 7.85e-9;
        material.m_G  = material.m_E / 2.0 * (1.0 + material.m_nu);
        dbServiceFactory->get<IIsotropicMaterialService> ()->Add (material);
    }

    // 写入
    {
        PSOLIDData solidProp;
        solidProp.m_id = 1;
        solidProp.m_mId = 1;
        dbServiceFactory -> get<IPSOLIDService>() -> Add(solidProp);
    }
}